/*
Copyright 2010  Murali Devi (profdevi@gmail.com)

This file is part of ComineGL Project.

ComineGL is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

ComineGL is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with ComineGL.  If not, see <http://www.gnu.org/licenses/>.

This code uses the irrlicht and irrklang libraries.  Please read
the libraries copyrights at 

	irrlicht library:  http://irrlicht.sourceforge.net
	irrklang library:  http://www.ambiera.com/irrklang

*/



//v1.2 copyright Comine.com 20101211S22
#include "MStdLib.h"
#include "MIrrlicht.h"
#include "MCGLAnimationInfo.h"


//******************************************************
//**  MCGLAnimationInfo class
//******************************************************
void MCGLAnimationInfo::ClearObject(void)
	{
	mArray=NULL;
	mRows=0;
	mCols=0;
	}


////////////////////////////////////////////////
int MCGLAnimationInfo::GetIndex(int row,int col,bool rowmajor)
	{
	if(rowmajor==true)
		{
		return row*mCols+col;
		}
	else
		{
		return col*mRows+row;
		}
	}


////////////////////////////////////////////////
MCGLAnimationInfo::MCGLAnimationInfo(void)
	{  ClearObject();  }


////////////////////////////////////////////////
MCGLAnimationInfo::~MCGLAnimationInfo(void)
	{  Destroy();  }


////////////////////////////////////////////////
bool MCGLAnimationInfo::Create(IVideoDriver *driver,const char *filename
				,int rows,int cols,int deltatime,bool rowmajor)
	{
	Destroy();
	if(rows<=0 || cols<=0 || filename==NULL || *filename==0 ||deltatime<=0)
		{
		Destroy();
		return false;
		}

	mRows=rows;
	mCols=cols;
	mDeltaTime=deltatime;

	mArray=new ITexture *[mRows*mCols];
	if(mArray==NULL)
		{
		Destroy();
		return false;
		}

	// Init the array
	int i;	
	for(i=0;i<mRows*mCols;++i)
		{  mArray[i]=NULL;  }

	//** Load up the images
	IImage *originalimage=driver->createImageFromFile(filename);
	if(originalimage==NULL)
		{
		Destroy();
		return false;
		}

	if(originalimage->getColorFormat()!=ECF_R8G8B8)
		{
		originalimage->drop();
		Destroy();
		return false;
		}

	//=Image is loaded
	int originalpixalbytes=originalimage->getBytesPerPixel();
	int originalpitch=originalimage->getPitch();
	int originalwidth=originalimage->getDimension().Width;
	int originalheight=originalimage->getDimension().Height;
	int newwidth=originalwidth/cols;
	int newheight=originalheight/rows;

	if(newwidth<1 || newheight<1 )
		{
		originalimage->drop();
		return false;
		}

	// Lock Surface
	char *originaldata=(char *)originalimage->lock();
	if(originaldata==NULL)
		{
		originalimage->drop();
		return false;
		}

	// Test Single Cell
	int cellrow;
	int cellcol;
	for(cellrow=0;cellrow<rows;++cellrow)
		{
		for(cellcol=0;cellcol<cols;++cellcol)
			{
			// Now Create a single image
			IImage *newimage=driver->createImageFromData(ECF_R8G8B8
					,dimension2d<u32>(newwidth,newheight),originaldata);
			if(newimage==NULL)
				{
				originalimage->unlock();
				originalimage->drop();
				return false;
				}

			int newpixelbytes=newimage->getBytesPerPixel();
			int newpitch=newimage->getPitch();

			MStdAssert(newimage->getDimension().Width == newwidth);
			MStdAssert(newimage->getDimension().Height == newheight);

			// Lock the target
			char *newdata=(char *)newimage->lock();

			if(newdata==NULL)
				{
				originalimage->unlock();
				originalimage->drop();		
				return false;
				}

			//=newsurface locked too

			int oldpos=originalpitch*cellrow*newheight+cellcol*newwidth*originalpixalbytes;
			int newpos=0;
			int r;
			for(r=0;r<newheight;++r)
				{
				MStdMemCpy(newdata+newpos,originaldata+oldpos,newwidth*originalpixalbytes);
				newpos+=newpitch;
				oldpos+=originalpitch;
				}

			newimage->unlock();

			//=We Now have the image

			//Create a new texture
			ITexture *newtexture=driver->addTexture("Sprite",newimage);
			if(newtexture==NULL)
				{
				newimage->drop();
				originalimage->unlock();
				originalimage->drop();
				return false;
				}

			// Drop Reference to image
			newimage->drop();

			int arrayindex=GetIndex(cellrow,cellcol,rowmajor);
			MStdAssert(arrayindex>=0 && arrayindex<mRows*mCols);

			mArray[arrayindex]=newtexture;
			newtexture->grab();
			driver->makeColorKeyTexture(newtexture,SColor(255,0,0,0) );
			newtexture->regenerateMipMapLevels();
			}
		}

	originalimage->unlock();
	originalimage->drop();
	return true;
	}


////////////////////////////////////////////////
bool MCGLAnimationInfo::Destroy(void)
	{
	if(mArray!=NULL)
		{
		int i;
		for(i=0;i<mRows*mCols;++i)
			{
			if(mArray[i]!=NULL)
				{  mArray[i]->drop();  }

			mArray[i]=NULL;
			}

		delete[] mArray;
		mArray=NULL;
		}

	ClearObject();
	return true;
	}


////////////////////////////////////////////////
int MCGLAnimationInfo::GetCount(void)
	{
	return mRows*mCols;
	}


////////////////////////////////////////////////
ITexture *MCGLAnimationInfo::Get(int index)
	{
	if(index<0) { index=-index;  }

	index=(index % (mRows*mCols) );
	MStdAssert(index>=0);
	return mArray[index];
	}


////////////////////////////////////////////////
int MCGLAnimationInfo::GetDeltaTime(void)
	{
	return mDeltaTime;	
	}

